/*
 * Copyright (c) 2011.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.skavookie.expressions

/**
 * Created by IntelliJ IDEA.
 * User: joshua
 * Date: 5/24/11
 * Time: 12:16 PM
 * To change this template use File | Settings | File Templates.
 */

trait ExprVisitor {
	vis: ExprVisitor =>
	def apply[T](expr: Expr[T]): Expr[T] = visit(expr)
	def visit[T](expr: Expr[T]): Expr[T] = expr match {
		case l: TLiteral[_] => literal(l)
		case g: TGet[_] => get(g)
		case s: TSet[_] => set(s)
		case w: TExprWrapper[_] => visit(w.getExpr)
		case e => e // default
	}
	def literal[T](expr: TLiteral[T]): Expr[T]
	def get[T](expr: TGet[T]): Expr[T]
	def set[T](expr: TSet[T]): Expr[T]
}

trait NumericExprVisitor extends ExprVisitor {
	numvis: NumericExprVisitor =>
	override def visit[T](expr: Expr[T]): Expr[T] = expr match {
		case p@PlusExpr(_,_) => plus(p)
		case m@MinusExpr(_,_) => minus(m)
		case t@TimesExpr(_,_) => times(t)
		case n@NegateExpr(_) => negate(n)
		case _ => super.visit(expr)
	}
	def plus[T](expr: PlusExpr[T]): Expr[T]
	def minus[T](expr: MinusExpr[T]): Expr[T]
	def times[T](expr: TimesExpr[T]): Expr[T]
	def negate[T](expr: NegateExpr[T]): Expr[T]
}

trait IntegralExprVisitor extends NumericExprVisitor {
	intvis: IntegralExprVisitor =>
	override def visit[T](expr: Expr[T]): Expr[T] = expr match {
		case q@QuotExpr(_,_) => quot(q)
		case r@RemExpr(_,_) => rem(r)
		case _ => super.visit(expr)
	}
	def quot[T](expr: QuotExpr[T]): Expr[T]
	def rem[T](expr: RemExpr[T]): Expr[T]
}

trait FractionalExprVisitor extends NumericExprVisitor {
	fravis: FractionalExprVisitor =>
	override def visit[T](expr: Expr[T]): Expr[T] = expr match {
		case d@DivExpr(_,_) => div(d)
		case _ => super.visit(expr)
	}
	def div[T](expr: DivExpr[T]): Expr[T]
}